package com.java.IO.zip_stream;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

public class ZipInputStreamAPI {
    // 解压
    public static void unzip(String zipPath, String unZipPath, String encode) throws Exception {
        File zipFile = new File(zipPath);
        if (!zipFile.exists() || !zipFile.getName().contains(".zip")) {
            throw new Exception("路径错误，请检查路径是否存在或正确。错误路径为" + zipFile.getPath());
        }
        
        File unZipFile = new File(unZipPath);
        if (!unZipFile.exists() || !unZipFile.isDirectory()) {
            throw new Exception("路径错误，请检查路径是否存在或正确。错误路径为" + unZipFile.getPath());
        }
        
        try (ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(zipFile), Charset.forName(encode))) {
            ZipEntry nextEntry;
            while ((nextEntry = zipInputStream.getNextEntry()) != null) {
                String nextEntryPath = nextEntry.toString();
                int lastSeparatorIndex = nextEntryPath.lastIndexOf(File.separator);
                if (lastSeparatorIndex != -1) {
                    String dirPath = nextEntryPath.substring(0, lastSeparatorIndex);
                    new File(unZipFile, dirPath).mkdirs();
                }
                
                try (FileOutputStream fileOutputStream = new FileOutputStream(new File(unZipFile, nextEntryPath))) {
                    int length = 0;
                    byte[] buffer = new byte[1024];
                    while ((length = zipInputStream.read(buffer)) != -1) {
                        fileOutputStream.write(buffer, 0, length);
                    }
                }
            }
        }
    }
    
    public static void main(String[] args) throws Exception {
        String zipPath1 = "File和IO流\\com\\java\\files\\zip\\zip\\unzip.zip";
        String zipPath2 = "File和IO流\\com\\java\\files\\zip\\zip\\students.zip";
        
        // 创建对象：创建规则主要依赖于构造形参InputStream的子类。参数2为字符集，默认UTF-8
        ZipInputStream zipInputStream1 = new ZipInputStream(new FileInputStream(zipPath1));
        ZipInputStream zipInputStream2 = new ZipInputStream(new FileInputStream(zipPath2), Charset.forName("UTF-8"));
        
        // getNextEntry：获取压缩包内的ZipEntry对象，若无数据则返回null
        System.out.println(zipInputStream1.getNextEntry()); // unzip\child\child1.txt
        System.out.println(zipInputStream1.getNextEntry()); // unzip\child\child2.txt
        System.out.println(zipInputStream1.getNextEntry()); // unzip\students.txt
        System.out.println(zipInputStream1.getNextEntry()); // null
        
        // read：读取压缩文件内数据，若无参数则一次读取一字节，若无数据则返回-1。若参数为字节数组且有数据则一次性读取字节数组长度的字节并存于该字节数组内同时返回读取到的字节长度
        System.out.println(zipInputStream2.getNextEntry());
        System.out.println(zipInputStream2.read()); // 97
        System.out.println(zipInputStream2.read()); // 57
        System.out.println(zipInputStream2.read()); // 45
        byte[] bytes = new byte[10];
        System.out.println(zipInputStream2.read(bytes, 5, 2)); // 2
        System.out.println(Arrays.toString(bytes)); // [0, 0, 0, 0, 0, 13, 10, 0, 0, 0] (读取2个数据到数组指定位置5)
        System.out.println(zipInputStream2.read(bytes)); // 6
        System.out.println(Arrays.toString(bytes)); // [97, 98, 99, 100, 100, 101, 10, 0, 0, 0] (残留数据10)
        System.out.println(zipInputStream2.read(bytes)); // -1
        System.out.println(Arrays.toString(bytes)); // [97, 98, 99, 100, 100, 101, 10, 0, 0, 0] (全都是残留数据)
        System.out.println(zipInputStream2.read()); // -1
        
        // close：关闭流并释放资源
        zipInputStream1.close();
        zipInputStream2.close();
        
        // 解压
        String unZipPath = "File和IO流\\com\\java\\files\\zip\\unzip";
        unzip(zipPath1, unZipPath, "UTF-8");
        unzip(zipPath2, unZipPath, "UTF-8");
    }
}
